package com.zhenghaijin.gw.filter;

import com.zhenghaijin.gw.utils.JsonUtils;
import com.zhenghaijin.gw.utils.JwtUtils;
import com.zhenghaijin.pojo.Result;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.netty.ByteBufFlux;

@Component
@Order(10)
public class AuthFilter implements GlobalFilter {
    /**
     * 自定义过滤器方法
     * 该方法用于处理进入网关的每个请求，可以在这里添加鉴权逻辑、日志记录等
     * login,register 不需要验证，
     * 其他请求都需要验证
     *
     * @param exchange 服务器Web交换对象，包含请求和响应的所有信息
     * @param chain 过滤器链对象，用于将请求传递到下一个过滤器或最终的目标服务
     * @return Mono<Void> 异步完成信号，表示过滤器处理完成
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取当前请求
        ServerHttpRequest request = exchange.getRequest();

        // 获取请求 url
        String url = request.getURI().getPath();
        System.out.println(url);
        // 对特定URL进行免验证处理
        if (url.contains("login")) {
            return chain.filter(exchange);
        }

        // 获取令牌
        String token = request.getHeaders().getFirst("Authorization");

        // 验证令牌有效性
        if (token != null && token.length() > 0 && JwtUtils.verifyToken(token)) {
            // 放行
            String strUserId = JwtUtils.getAudience(token);
            request.mutate().header("userId", strUserId);
            return chain.filter(exchange);
        }
        //  令牌无效时，给前端一个响应
        Result result = new Result(555, "令牌无效，请登录 ！", null);

        // 将响应结果转换为JSON格式
        String json = JsonUtils.objectToJson(result);

        // 获取响应对象
        ServerHttpResponse response = exchange.getResponse();
        //  设置响应状态码为200
        response.setStatusCode(HttpStatus.OK);
        // 完成响应，结束请求处理
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");

        // 写入响应内容并完成响应
        return response.writeAndFlushWith(Flux.just(ByteBufFlux.just(response.bufferFactory().wrap(json.getBytes()))));
    }
}
